from qturboframe.lib.utils.by import By
from qturboframe.lib.webdriver.exceptions import SeleniumError
from qturboframe.lib.report.log import logger
from qturboframe.public_ui.h_ui.table import Table as HuiTable
from BladeFerm.hui2_app.hui2_lib.page import Page
from BladeFerm.hui2_app.hui2_lib.list import List
from .base_table import BaseTable
import time

from BladeFerm.hui12_common.function import display_wait, get_params


class Table(HuiTable):
    '''
    表格操作对象封装。包括表格上方的按钮操作栏 和 表格底部的分页栏
    '''

    def __init__(self, element_para, father=None, timeout=1, index=1):
        '''
        查找表格对象
        :param element_para: 就是同idname传参。
            含有 text 属性，走if分支： 例如：{'text': '唯一客户号'}；
                       否则走else分支。
        :param father:
        :param timeout:
        :param index:
        '''
        self.timeout = timeout
        self.datagrid = None
        if isinstance(element_para, dict) and By.TEXT in list(element_para.keys())[0]:
            text = element_para.get(By.TEXT)
            # xpath = ".//table//*[contains(normalize-space(text()),'{}')]//ancestor::div[contains(@class,'h-table-wrapper')][1]".format(text)
            xpath = f".//table//*[contains(normalize-space(text()),'{text}')]//ancestor::div[contains(@class,'h-datagrid')]"
            elements = father.find_elements_by_attribute(By.XPATH, xpath, timeout=timeout)
            if len(elements) != 0:
                # super().__init__(elements[index-1], father, timeout)
                self.datagrid = elements[index-1]
            else:
                raise SeleniumError("按照此路径'{}'没有找到对应的元素！".format(xpath))
        else:
            element_by, element_value, assist = get_params(element_para)
            temps = father.find_elements_by_attribute(element_by, element_value, assist=assist, timeout=timeout)
            #获取到第一个可见的table
            for temp in temps:
                if temp.is_displayed():
                    # super().__init__(temp, father, timeout)
                    self.datagrid = temp
                    break
            else:
                raise SeleniumError("按照此路径'{}'没有查找到可见的table".format(element_para))
        self.table_box()
        self.toolbar()
        self.page()
        self.fixed()


    def table_box(self, idname=None):
        if not idname:
            idname = {By.CSS_SELECTOR: 'div.h-table-wrapper'}
        logger.debug(f'table_box idname: {idname}')
        element_by, element_value, assist = get_params(idname)
        self._element = self.datagrid.find_element_by_attribute(element_by, element_value, assist, timeout=self.timeout)

    def page(self, idname=None, father=None):
        '''
        获取hui表格分页栏对象
        重写说明：操作员中心Page类的xpth定位和hui标准定位的xpth不同

        :Args:
         - idname: 分页栏的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 分页栏的祖先级元素，可以给分页栏查找限定范围，这样就不需要在整个页面中查找

        :Example:
         - 例: table.page({'xpath':'./following-sibling::ul[@class="h-page"]'})
        '''
        if father is None:
            father = self.datagrid
        if idname:
            self._page = Page(idname, father, 1)
        else:
            self._page = Page({By.CSS_SELECTOR: 'ul.h-page'}, father, 5)
        return self._page

    def toolbar(self, idname=None, father=None):
        if father is None:
            father = self.datagrid
        if idname:
            self._toolbar = List(idname, father, 1)
        else:
            self._toolbar = List({By.CSS_SELECTOR: 'div.h-datagrid-toolbar'}, father, 5)
        return self._toolbar

    def refresh(self):
        btn_ref = self._toolbar.foud_target(
            idname={'xpath': './/i[contains(@class, "h-icon-refresh")]//ancestor::button'})
        if btn_ref:
            btn_ref[0].click()
            logger.info(f'点击刷新图标')
        else:
            raise SeleniumError(f'没有找到刷新图标！')

    def export(self, is_all=True, rows=None, turn_page=False):
        '''
        导出表格数据。
        :param is_all: 是否导出全部行
        :param rows: 导出指定行时，给出导出的行的筛选条件。
        :param turn_page: 导出指定行时，根据筛选条件勾选数据时，是否进行翻页勾选
        :return:
        '''
        if is_all:
            button_name = '导出全部行'
        else:
            button_name = '导出选中行'
            self.select_rows(rows, turn_page=turn_page)
        # 点击导出图标，展开下拉选择
        btn_exp = self._toolbar.foud_target(
            idname={'xpath': './/i[contains(@class, "icon-upload1")]//ancestor::button'})
        if btn_exp:
            btn_exp[0].click()
            logger.info(f'点击 导出 图标')
        else:
            raise SeleniumError(f'没有找到导出图标！')
        # 点击 导出xx
        self._toolbar.foud_target({By.CSS_SELECTOR: 'li.h-dropdown-item>button'})
        self._toolbar.click_target(button_name)

    def set_display_cols(self, names=None):
        '''
        设置表格显示的列。
        :param names: 要取消的列名
        :return:
        '''
        display_cols = []
        if not isinstance(names, list):
            names = names.split(',')
        if names:
            logger.warning(f'没有要取消显示的列，按照默认列显示。')
            return False
        # 点击 设置 图标，展开下拉选择
        btn_set = self._toolbar.foud_target(
            idname={'xpath': './/i[contains(@class, "h-icon-t-b-setting")]//ancestor::button'})
        if btn_set:
            btn_set[0].click()
            logger.info(f'点击 设置 图标')
        else:
            raise SeleniumError(f'没有找到 设置 图标！')
        # 勾选显示列
        labels = self._toolbar.foud_target({By.CSS_SELECTOR: 'div.h-checkbox-group>label.h-checkbox-group-item'})
        for lab in labels:
            text = lab.text
            if text in names:
                lab.click()
                logger.info(f'取消 {text} 列的显示！')
            else:
                display_cols.append(text)
        return display_cols

    def check_cells_exist(self, table_dict, turn_page=False):
        '''
        检查单元格是否存在
        重新说明：增加了多列单项的表格校验（例：{'列1': 'xx', '列2': 'xx'}）

        :Args:
         - table_dict: 一组单元格列名和单元格内容，字典类型，例：{列名1:'内容1,内容2'}
         - turn_page: 是否自动翻页，默认关闭自动翻页查找功能

        :Example:
         - 例: table.check_cells_exist({'姓名':'admin, manager'}, True)
        '''
        # 表格数据检查
        key_list = list(table_dict.keys())
        for key in key_list:
            if table_dict.get(key) == '-':
                table_dict.pop(key)
        if not table_dict:
            raise AttributeError('表格检查条件为空！')
        if turn_page:
            if self._page.exist():
                self._page.to_first()
        # 查看是否存在冻结列
        fixed_title_list = list()
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'css selector': 'div.h-table-fixed-header>table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
        # 获取列名列表
        head_table = BaseTable({By.CSS_SELECTOR: 'div.h-table-header>table'}, self._element, self.timeout)
        title_list = head_table.get_title_list()
        logger.debug('表格显示列名：' + str(title_list))
        # 查找单元格
        value_list = len(list(table_dict.values())[0].split(','))
        key_list = len(list(table_dict.keys()))
        if key_list > 1:
            row_list = self.__get_row_indexes(fixed_title_list, title_list, table_dict, turn_page)
            if len(set(row_list)) == value_list:
                logger.info('单元格存在，检查通过')
            else:
                raise SeleniumError('有单元格不存在，检查不通过，请检查数据后重试！')
        else:
            search_value_list = table_dict.get(list(table_dict.keys())[0]).split(',')
            for value in search_value_list:
                search_dict = {list(table_dict.keys())[0]:value}
                row = self._get_row_index(fixed_title_list, title_list, search_dict, turn_page)
                if row:
                    logger.info('列名为{}，内容为{}的单元格存在，检查通过！'.format(
                        list(table_dict.keys())[0], value))
                else:
                    raise SeleniumError('列名为{}，内容为{}的单元格不存在，检查不通过！'.format(
                        list(table_dict.keys())[0], value))

    def check_rows_reload_finish(self, timeout=10):
        '''
        判定表格行数是否加载完成
        :return:
        '''
        return display_wait(idname={By.CSS_SELECTOR: 'tr.h-table-row'}, flag=0, timeout=timeout, driver=self.element)

    def nocheckbox_select_rows(self, table_dict, title_name, turn_page=False):
        '''
        表格单元格点击选中(针对一些不带checkbox勾选的数据行)

        :Args:
         - table_dict: 一组单元格列名和单元格内容，字典类型，例：{列名1:'内容1,内容2'}
         - title_name: 表格所要勾选的列名
         - turn_page: 是否自动翻页，默认关闭自动翻页查找功能

        :Example:
         - 例: table.nocheckbox_select_rows({'姓名':'admin, manager'}, 列名,True)
        '''
        table_data = self.get_cell(table_dict, title_name)
        if table_data:
            # 进行表格勾选
            table_data.click()
            # hui点击触发时间有延迟
            time.sleep(0.5)

    def _get_row_index(self, fixed_title_list, title_list, table_dict, turn_page=False):
        re_disabled = r'h-page-disabled'
        key_list = list(table_dict.keys())
        # 以输入数据作为索引查找表格行数
        rows = 0
        row_list = list()
        for i, key in enumerate(key_list):
            temp_list = list()
            text_list = list()
            # 查看是否存在冻结列
            if fixed_title_list:
                # 获取冻结列内容列表
                fixed_body_table = BaseTable(
                    {'css selector': 'div.h-table-fixed-body>table'}, self._fixed_div, self.timeout)
                try:
                    title_index = fixed_title_list.index(key)
                except:
                    pass
                else:
                    text_list = fixed_body_table.get_text_list(len(fixed_title_list), int(title_index + 1))
            # 获取指定列内容列表
            body_table = BaseTable(
                {'xpath': './/div[@class="h-table-body"]/table'}, self._element, self.timeout)
            if len(text_list) == 0:
                try:
                    title_index = title_list.index(key)
                except:
                    continue
                else:
                    text_list = body_table.get_text_list(len(title_list), int(title_index + 1))
            if i == 0:
                rows = len(text_list)
                row_list = list(range(1, rows + 1))
            for j in row_list:
                if text_list[j - 1] == table_dict[key]:
                    temp_list.append(j)
            row_list = temp_list
            if len(row_list) == 0:
                break
        # 未找到数据行则进行表格翻页
        if len(row_list) > 0:
            return row_list[0]
        else:
            if turn_page:
                if self._page.exist():
                    if self._page.is_last():
                        return 0
                    else:
                        self._page.to_next()
                        return self._get_row_index(fixed_title_list, title_list, table_dict, turn_page)
                else:
                    return 0
            else:
                return 0

    def __get_row_indexes(self, fixed_title_list, title_list, table_dict, turn_page=False):
        key_list = list(table_dict.keys())
        # logger.debug('表格查找列名索引：' + str(key_list))
        # 以输入数据作为索引查找表格行数
        row_list = list()
        rows = 0
        for i, key in enumerate(key_list):
            text_list = list()
            temp_list = list()
            # 查看是否存在冻结列
            if fixed_title_list:
                # 获取冻结列内容列表
                fixed_body_table = BaseTable(
                    {'css selector': 'div.h-table-fixed-body>table'}, self._fixed_div, self.timeout)
                try:
                    title_index = fixed_title_list.index(key)
                    # logger.debug('第' + str(title_index + 1) + '列，名称：' + key)
                except:
                    pass
                else:
                    text_list = fixed_body_table.get_text_list(len(fixed_title_list), int(title_index + 1))
            # 获取指定列内容列表
            if len(text_list) == 0:
                try:
                    title_index = title_list.index(key)
                    logger.debug('第' + str(title_index + 1) + '列，名称：' + key)
                except:
                    # logger.debug('表格中没有列名：' + key)
                    pass
                else:
                    body_table = BaseTable(
                        {'xpath': './div/div[@class=\'h-table-body\']/table'}, self._element, self.timeout)
                    text_list = body_table.get_text_list(len(title_list), int(title_index + 1))
            if i == 0:
                rows = len(text_list)
                logger.debug('当前页显示行数：' + str(rows))
                row_list = list(range(1, rows + 1))
            content_list = table_dict[key].split(',')
            for j in row_list:
                for k in content_list:
                    if text_list[j - 1] == k:
                        # logger.debug('要查找的内容：' + k)
                        # logger.debug('第' + str(j) + '行，内容：' + text_list[j - 1])
                        temp_list.append(j)
            row_list = temp_list
            if len(row_list) == 0:
                break
        # 判断是否找到数据行
        if len(row_list) > 0:
            logger.debug(f'row_list: {row_list}')
            return row_list
        else:
            # 翻页查找
            if turn_page:
                if self._page.exist():
                    if not self._page.is_last():
                        self._page.to_next()
                        logger.debug("翻下一页查找。")
                        row_list.extend(self.__get_row_indexes(
                            fixed_title_list, title_list, table_dict, turn_page))
                    else:
                        return row_list
                else:
                    return []
            else:
                return []